/**
 * 模型缓存管理器
 * 负责管理模型的加载状态和缓存
 */

export class ModelCacheManager {
    constructor() {
        // 模型缓存：Map<modelId, Object3D>
        this.modelCache = new Map();
        
        // 模型加载状态：Map<modelId, 'loading' | 'loaded' | 'error' | 'downloading'>
        this.loadingStatus = new Map();
        
        // 模型元数据：Map<modelId, { name, format, path, ... }>
        this.modelMetadata = new Map();
        
        // 正在加载的Promise：Map<modelId, Promise>
        this.loadingPromises = new Map();
        
        // 监听器：用于通知UI更新
        this.listeners = new Set();
        
        // 🎯 下载管理
        // 下载任务控制器：Map<modelId, AbortController>
        this.downloadControllers = new Map();
        
        // 下载进度：Map<modelId, { loaded: number, total: number, percentage: number }>
        this.downloadProgress = new Map();
        
        // 是否正在批量下载
        this.isBatchDownloading = false;
        
        // 批量下载控制器
        this.batchDownloadController = null;
        
        // 🎯 并发下载配置
        // 最大并发下载数（从项目配置读取，默认为 3）
        this.maxConcurrentDownloads = 3;
        
        // 当前正在进行的并发下载数
        this.currentConcurrentDownloads = 0;
    }
    
    /**
     * 添加状态变化监听器
     * @param {Function} listener - 回调函数 (modelId, status) => void
     */
    addListener(listener) {
        this.listeners.add(listener);
    }
    
    /**
     * 移除监听器
     */
    removeListener(listener) {
        this.listeners.delete(listener);
    }
    
    /**
     * 通知所有监听器
     */
    notifyListeners(modelId, status) {
        this.listeners.forEach(listener => {
            try {
                listener(modelId, status);
            } catch (error) {
                console.error('❌ 监听器执行失败:', error);
            }
        });
    }
    
    /**
     * 从项目配置加载并发下载数
     * @param {Object} projectConfig - 项目配置对象
     */
    loadMaxConcurrentDownloadsFromProject(projectConfig) {
        if (projectConfig && projectConfig.maxConcurrentDownloads) {
            const value = projectConfig.maxConcurrentDownloads;
            if (value >= 1 && value <= 20) {
                this.maxConcurrentDownloads = value;
            } else {
                console.warn(`⚠️ 项目配置中的并发下载数无效 (${value})，使用默认值 3`);
                this.maxConcurrentDownloads = 3;
            }
        } else {
            this.maxConcurrentDownloads = 3;
        }
    }
    
    /**
     * 获取最大并发下载数
     * @returns {number}
     */
    getMaxConcurrentDownloads() {
        return this.maxConcurrentDownloads;
    }
    
    /**
     * 检查模型是否已加载到缓存
     * @param {string} modelId - 模型ID
     * @returns {boolean}
     */
    isModelLoaded(modelId) {
        return this.modelCache.has(modelId);
    }
    
    /**
     * 检查模型是否正在加载
     * @param {string} modelId - 模型ID
     * @returns {boolean}
     */
    isModelLoading(modelId) {
        return this.loadingStatus.get(modelId) === 'loading';
    }
    
    /**
     * 获取模型的加载状态
     * @param {string} modelId - 模型ID
     * @returns {'loaded' | 'loading' | 'error' | 'unloaded'}
     */
    getLoadingStatus(modelId) {
        if (this.modelCache.has(modelId)) {
            return 'loaded';
        }
        return this.loadingStatus.get(modelId) || 'unloaded';
    }
    
    /**
     * 从缓存中获取模型（返回克隆，保留UUID）
     * @param {string} modelId - 模型ID
     * @returns {THREE.Object3D | null}
     */
    getModelFromCache(modelId) {
        if (!this.modelCache.has(modelId)) {
            return null;
        }
        
        const cachedModel = this.modelCache.get(modelId);
        
        // ⭐ 返回深度克隆，但保留所有UUID（关键修复！）
        // 这样meshMaterials中保存的UUID仍然有效
        return this.cloneWithUUID(cachedModel);
    }
    
    /**
     * 克隆材质并确保所有属性正确复制
     * @param {THREE.Material} clonedMat - 已克隆的材质
     * @param {THREE.Material} originalMat - 原始材质
     * @returns {THREE.Material} 完整克隆的材质
     */
    cloneMaterialWithProperties(clonedMat, originalMat) {
        if (!clonedMat || !originalMat) return clonedMat;
        
        // Three.js的clone()方法应该已经复制了大部分属性
        // 但为了确保万无一失，我们手动验证和复制关键属性
        
        // 确保颜色正确复制（强制复制，即使看起来已经复制了）
        if (originalMat.color) {
            if (!clonedMat.color) {
                clonedMat.color = originalMat.color.clone();
            } else {
                clonedMat.color.copy(originalMat.color);
            }
        }
        
        // 确保发光颜色正确复制
        if (originalMat.emissive) {
            if (!clonedMat.emissive) {
                clonedMat.emissive = originalMat.emissive.clone();
            } else {
                clonedMat.emissive.copy(originalMat.emissive);
            }
        }
        
        // 确保高光颜色正确复制（Phong材质）
        if (originalMat.specular) {
            if (!clonedMat.specular) {
                clonedMat.specular = originalMat.specular.clone();
            } else {
                clonedMat.specular.copy(originalMat.specular);
            }
        }
        
        // 确保PBR属性正确复制
        if (originalMat.metalness !== undefined && clonedMat.metalness !== undefined) {
            clonedMat.metalness = originalMat.metalness;
        }
        if (originalMat.roughness !== undefined && clonedMat.roughness !== undefined) {
            clonedMat.roughness = originalMat.roughness;
        }
        
        // 确保透明度相关属性
        if (originalMat.opacity !== undefined) {
            clonedMat.opacity = originalMat.opacity;
        }
        if (originalMat.transparent !== undefined) {
            clonedMat.transparent = originalMat.transparent;
        }
        
        // 确保其他重要属性
        if (originalMat.side !== undefined) {
            clonedMat.side = originalMat.side;
        }
        if (originalMat.emissiveIntensity !== undefined && clonedMat.emissiveIntensity !== undefined) {
            clonedMat.emissiveIntensity = originalMat.emissiveIntensity;
        }
        
        // 确保 Phong 材质的光泽度
        if (originalMat.shininess !== undefined && clonedMat.shininess !== undefined) {
            clonedMat.shininess = originalMat.shininess;
        }
        
        // 确保反射率（reflectivity）
        if (originalMat.reflectivity !== undefined && clonedMat.reflectivity !== undefined) {
            clonedMat.reflectivity = originalMat.reflectivity;
        }
        
        // 确保折射率（refractionRatio）
        if (originalMat.refractionRatio !== undefined && clonedMat.refractionRatio !== undefined) {
            clonedMat.refractionRatio = originalMat.refractionRatio;
        }
        
        // 确保其他渲染属性
        if (originalMat.flatShading !== undefined) {
            clonedMat.flatShading = originalMat.flatShading;
        }
        if (originalMat.wireframe !== undefined) {
            clonedMat.wireframe = originalMat.wireframe;
        }
        if (originalMat.vertexColors !== undefined) {
            clonedMat.vertexColors = originalMat.vertexColors;
        }
        
        // 纹理贴图应该已经被clone()正确处理，但我们验证一下
        const textureProps = ['map', 'normalMap', 'bumpMap', 'roughnessMap', 'metalnessMap', 
                              'aoMap', 'emissiveMap', 'specularMap', 'envMap'];
        textureProps.forEach(prop => {
            if (originalMat[prop] && !clonedMat[prop]) {
                clonedMat[prop] = originalMat[prop];
            }
        });
        
        // 标记材质需要更新
        clonedMat.needsUpdate = true;
        
        return clonedMat;
    }
    
    /**
     * 深度克隆对象，并保留所有对象的UUID
     * @param {THREE.Object3D} source - 源对象
     * @returns {THREE.Object3D} 克隆的对象（保留UUID）
     */
    cloneWithUUID(source) {
        // 使用Three.js的clone方法克隆对象
        const cloned = source.clone();
        
        // 创建UUID映射表：记录原始对象树中每个对象的UUID
        const uuidMap = new Map();
        
        // 第一步：遍历原始对象树，收集所有UUID
        source.traverse((original) => {
            uuidMap.set(original.uuid, original);
        });
        
        // 第二步：遍历克隆对象树，恢复UUID
        const originalArray = [];
        source.traverse((obj) => originalArray.push(obj));
        
        const clonedArray = [];
        cloned.traverse((obj) => clonedArray.push(obj));
        
        // 确保两个数组长度一致（相同的树结构）
        if (originalArray.length === clonedArray.length) {
            for (let i = 0; i < originalArray.length; i++) {
                const originalObj = originalArray[i];
                const clonedObj = clonedArray[i];
                
                // ⭐ 恢复UUID（核心修复）
                clonedObj.uuid = originalObj.uuid;
                
                // 同时恢复name（确保一致性）
                clonedObj.name = originalObj.name;
                
                // 如果是Mesh，需要特别处理材质
                if (clonedObj.isMesh && originalObj.isMesh) {
                    // 克隆材质以避免共享（确保所有属性正确复制）
                    if (Array.isArray(originalObj.material)) {
                        clonedObj.material = originalObj.material.map((originalMat) => {
                            // 先调用材质的clone()，然后再验证属性
                            const clonedMat = originalMat.clone();
                            return this.cloneMaterialWithProperties(clonedMat, originalMat);
                        });
                    } else if (originalObj.material) {
                        // 先调用材质的clone()，然后再验证属性
                        const clonedMat = originalObj.material.clone();
                        clonedObj.material = this.cloneMaterialWithProperties(
                            clonedMat, 
                            originalObj.material
                        );
                    }
                }
            }
        } else {
            console.warn(`⚠️ [ModelCache] 原始对象和克隆对象的子对象数量不一致`);
            console.warn(`   原始: ${originalArray.length}, 克隆: ${clonedArray.length}`);
        }
        
        return cloned;
    }
    
    /**
     * 将模型添加到缓存
     * @param {string} modelId - 模型ID
     * @param {THREE.Object3D} object3D - 3D对象
     * @param {Object} metadata - 模型元数据
     */
    addToCache(modelId, object3D, metadata = {}) {
        this.modelCache.set(modelId, object3D);
        this.modelMetadata.set(modelId, metadata);
        this.loadingStatus.set(modelId, 'loaded');
        this.loadingPromises.delete(modelId);
        // 通知监听器
        this.notifyListeners(modelId, 'loaded');
    }
    
    /**
     * 设置模型为加载中状态
     * @param {string} modelId - 模型ID
     * @param {Promise} loadingPromise - 加载Promise
     */
    setLoading(modelId, loadingPromise) {
        this.loadingStatus.set(modelId, 'loading');
        this.loadingPromises.set(modelId, loadingPromise);
        // 通知监听器
        this.notifyListeners(modelId, 'loading');
    }
    
    /**
     * 设置模型加载错误
     * @param {string} modelId - 模型ID
     * @param {Error} error - 错误对象
     */
    setError(modelId, error) {
        this.loadingStatus.set(modelId, 'error');
        this.loadingPromises.delete(modelId);
        
        console.error(`❌ 模型加载失败: ${modelId}`, error);
        
        // 通知监听器
        this.notifyListeners(modelId, 'error');
    }
    
    /**
     * 等待模型加载完成（如果正在加载）
     * @param {string} modelId - 模型ID
     * @returns {Promise<THREE.Object3D>}
     */
    async waitForModel(modelId) {
        if (this.modelCache.has(modelId)) {
            return this.getModelFromCache(modelId);
        }
        
        if (this.loadingPromises.has(modelId)) {
            await this.loadingPromises.get(modelId);
            return this.getModelFromCache(modelId);
        }
        
        throw new Error(`模型未在缓存中且未在加载: ${modelId}`);
    }
    
    /**
     * 清除特定模型的缓存
     * @param {string} modelId - 模型ID
     */
    removeFromCache(modelId) {
        const model = this.modelCache.get(modelId);
        if (model) {
            // 释放资源
            model.traverse((child) => {
                if (child.isMesh) {
                    if (child.geometry) child.geometry.dispose();
                    if (child.material) {
                        if (Array.isArray(child.material)) {
                            child.material.forEach(m => m.dispose());
                        } else {
                            child.material.dispose();
                        }
                    }
                }
            });
        }
        
        this.modelCache.delete(modelId);
        this.modelMetadata.delete(modelId);
        this.loadingStatus.delete(modelId);
        this.loadingPromises.delete(modelId);
        // 通知监听器
        this.notifyListeners(modelId, 'unloaded');
    }
    
    /**
     * 清空所有缓存
     */
    clearAll() {
        // 释放所有资源
        this.modelCache.forEach((model, modelId) => {
            this.removeFromCache(modelId);
        });
        
        this.modelCache.clear();
        this.modelMetadata.clear();
        this.loadingStatus.clear();
        this.loadingPromises.clear();
    }
    
    /**
     * 获取缓存统计信息
     * @returns {Object}
     */
    getStats() {
        return {
            cached: this.modelCache.size,
            loading: Array.from(this.loadingStatus.values()).filter(s => s === 'loading').length,
            error: Array.from(this.loadingStatus.values()).filter(s => s === 'error').length
        };
    }
    
    /**
     * 获取所有已缓存的模型ID列表
     * @returns {string[]}
     */
    getCachedModelIds() {
        return Array.from(this.modelCache.keys());
    }
    
    /**
     * 获取模型元数据
     * @param {string} modelId - 模型ID
     * @returns {Object | null}
     */
    getMetadata(modelId) {
        return this.modelMetadata.get(modelId) || null;
    }
    
    // ============ 下载管理功能 ============
    
    /**
     * 下载单个模型到缓存
     * @param {Object} modelData - 模型数据 { id, path, format, name, ... }
     * @param {Function} loaderFunction - 加载器函数 (url) => Promise<Object3D>
     * @returns {Promise<Object3D>}
     */
    async downloadModel(modelData, loaderFunction) {
        const { id: modelId, path, name } = modelData;
        
        // 如果已经加载或正在加载，直接返回
        if (this.isModelLoaded(modelId)) {
            return this.getModelFromCache(modelId);
        }
        
        if (this.isModelLoading(modelId) || this.isModelDownloading(modelId)) {
            return this.waitForModel(modelId);
        }
        
        // 创建下载控制器
        const controller = new AbortController();
        this.downloadControllers.set(modelId, controller);
        
        // 设置下载状态
        this.loadingStatus.set(modelId, 'downloading');
        this.downloadProgress.set(modelId, { loaded: 0, total: 0, percentage: 0 });
        this.notifyListeners(modelId, 'downloading');
        
        try {
            
            // 创建加载Promise
            const loadPromise = loaderFunction(path, controller.signal, (loaded, total) => {
                // 更新下载进度
                const percentage = total > 0 ? Math.round((loaded / total) * 100) : 0;
                this.downloadProgress.set(modelId, { loaded, total, percentage });
                this.notifyListeners(modelId, 'downloading', { loaded, total, percentage });
            });
            
            this.setLoading(modelId, loadPromise);
            
            // 等待加载完成
            const object3D = await loadPromise;
            
            // 添加到缓存
            this.addToCache(modelId, object3D, modelData);
            
            // 清理下载控制器
            this.downloadControllers.delete(modelId);
            this.downloadProgress.delete(modelId);
            return object3D;
            
        } catch (error) {
            // 检查是否是用户取消
            if (error.name === 'AbortError' || error.message.includes('abort')) {
                this.loadingStatus.set(modelId, 'unloaded');
            } else {
                console.error(`❌ 下载失败: ${name}`, error);
                this.setError(modelId, error);
            }
            
            // 清理
            this.downloadControllers.delete(modelId);
            this.downloadProgress.delete(modelId);
            this.notifyListeners(modelId, 'unloaded');
            
            throw error;
        }
    }
    
    /**
     * 取消单个模型的下载
     * @param {string} modelId - 模型ID
     */
    cancelDownload(modelId) {
        const controller = this.downloadControllers.get(modelId);
        if (controller) {
            controller.abort();
            this.downloadControllers.delete(modelId);
            this.downloadProgress.delete(modelId);
            this.loadingStatus.set(modelId, 'unloaded');
            this.notifyListeners(modelId, 'unloaded');
        }
    }
    
    /**
     * 批量下载所有未下载的模型（支持并发控制）
     * @param {Array} allModels - 所有模型数据
     * @param {Function} loaderFunction - 加载器函数
     * @returns {Promise<{success: number, failed: number, cancelled: number}>}
     */
    async downloadAllModels(allModels, loaderFunction) {
        if (this.isBatchDownloading) {
            console.warn('⚠️ 已有批量下载任务在进行中');
            return;
        }
        
        this.isBatchDownloading = true;
        this.batchDownloadController = new AbortController();
        this.currentConcurrentDownloads = 0;
        
        const unloadedModels = allModels.filter(model => !this.isModelLoaded(model.id));
        
        const results = {
            success: 0,
            failed: 0,
            cancelled: 0
        };
        
        try {
            // 使用并发控制的下载队列
            const downloadQueue = [...unloadedModels];
            const activeDownloads = new Set();
            
            // 下载单个模型的包装函数
            const downloadOne = async (model) => {
                // 检查是否被取消
                if (this.batchDownloadController.signal.aborted) {
                    results.cancelled++;
                    return;
                }
                
                this.currentConcurrentDownloads++;
                
                try {
                    await this.downloadModel(model, loaderFunction);
                    results.success++;
                } catch (error) {
                    if (error.name === 'AbortError' || error.message.includes('abort')) {
                        results.cancelled++;
                    } else {
                        results.failed++;
                        console.error(`❌ 下载失败: ${model.name}`, error);
                    }
                } finally {
                    this.currentConcurrentDownloads--;
                }
            };
            
            // 持续处理队列直到所有模型都被处理
            while (downloadQueue.length > 0 || activeDownloads.size > 0) {
                // 检查是否被取消
                if (this.batchDownloadController.signal.aborted) {
                    // 等待当前正在下载的任务完成
                    await Promise.all(activeDownloads);
                    break;
                }
                
                // 填充下载槽位直到达到最大并发数
                while (downloadQueue.length > 0 && activeDownloads.size < this.maxConcurrentDownloads) {
                    const model = downloadQueue.shift();
                    const downloadPromise = downloadOne(model).finally(() => {
                        activeDownloads.delete(downloadPromise);
                    });
                    activeDownloads.add(downloadPromise);
                }
                
                // 等待至少一个下载任务完成
                if (activeDownloads.size > 0) {
                    await Promise.race(activeDownloads);
                }
            }
        } catch (error) {
            console.error('❌ 批量下载过程中发生错误:', error);
        } finally {
            this.isBatchDownloading = false;
            this.batchDownloadController = null;
            this.currentConcurrentDownloads = 0;
        }
        
        return results;
    }
    
    /**
     * 取消所有下载任务
     */
    cancelAllDownloads() {
        
        // 取消批量下载
        if (this.batchDownloadController) {
            this.batchDownloadController.abort();
        }
        
        // 取消所有单个下载
        const modelIds = Array.from(this.downloadControllers.keys());
        modelIds.forEach(modelId => this.cancelDownload(modelId));
        
        this.isBatchDownloading = false;
        this.batchDownloadController = null;
    }
    
    /**
     * 检查模型是否正在下载
     * @param {string} modelId - 模型ID
     * @returns {boolean}
     */
    isModelDownloading(modelId) {
        return this.loadingStatus.get(modelId) === 'downloading';
    }
    
    /**
     * 获取下载进度
     * @param {string} modelId - 模型ID
     * @returns {Object | null} { loaded, total, percentage }
     */
    getDownloadProgress(modelId) {
        return this.downloadProgress.get(modelId) || null;
    }
    
    /**
     * 获取当前正在下载的模型数量
     * @returns {number}
     */
    getDownloadingCount() {
        return this.downloadControllers.size;
    }
    
    /**
     * 检查是否有下载任务在进行
     * @returns {boolean}
     */
    hasActiveDownloads() {
        return this.downloadControllers.size > 0 || this.isBatchDownloading;
    }
}

// 创建全局单例
const modelCacheManager = new ModelCacheManager();

// 暴露到全局
window.modelCacheManager = modelCacheManager;

export default modelCacheManager;

